package com.bearhy.jqadmin.shiro;


import com.bearhy.jqadmin.model.JqadminUser;
import com.bearhy.jqadmin.model.SysMenu;
import com.bearhy.jqadmin.model.SysRole;
import com.bearhy.jqadmin.service.JqadminUserService;
import com.bearhy.jqadmin.service.SysMenuService;
import com.bearhy.jqadmin.service.SysRoleService;
import com.github.pagehelper.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
 * 自定义用户认证和添加授权类
 */
public class MyShiroRealm extends AuthorizingRealm {

    private static final Log log = LogFactory.getLog(MyShiroRealm.class);

    @Autowired
    private JqadminUserService jqadminUserService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysMenuService sysMenuService;
    /**
     * 授权
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        log.info("权限配置-->MyShiroRealm.doGetAuthorizationInfo()");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        JqadminUser userInfo  = (JqadminUser)principals.getPrimaryPrincipal();
        List<SysRole> roles = sysRoleService.getRoleListByUserRoldIds(userInfo.getUserRoles());
        for(SysRole role: roles){
            //添加角色
            if(!StringUtil.isEmpty(role.getRoleCode())){
                info.addRole(role.getRoleCode());
            }
            //添加权限
            List<SysMenu> menus = sysMenuService.getMenuPermissions(role.getRoleMenuIds());
            for(SysMenu menu : menus){
                if(!StringUtil.isEmpty(menu.getMenuPerms())) {
                    info.addStringPermission(menu.getMenuPerms());
                }
            }
        }
        return info;
    }

    /**
     * 认证
     * 抛出异常类型：
     * UnknownAccountException：
     * IncorrectCredentialsException：密码错误
     * DisabledAccountException：账号被禁用
     * LockedAccountException：账号被锁定
     * ExcessiveAttemptsException：登录失败次数过多
     * ExpiredCredentialsException：凭证过期
     * ConcurrentAccessException：多次登录异常
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 1.从主体传过来的认证信息中，获得用户名
        String username = (String) token.getPrincipal();
        // 2.通过用户名到数据库中获取凭证
        JqadminUser user = jqadminUserService.getByUserName(username);
        //账号不存在，抛出相应异常
        if(user == null){
            throw new UnknownAccountException();
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                username,
                user.getUserPassword(),
                ByteSource.Util.bytes(user.getUserSalt()),
                getName());
        return info;
    }

    /**
     * 清空当前用户缓存
     */
    public void clearCached() {
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        super.clearCache(principals);
        log.info("清空shiro当前用户缓存成功");
    }

    /**
     * 清空所有缓存
     */
    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
        log.info("清空shiro所有缓存成功");
    }

    private void clearAllCachedAuthorizationInfo() {
        if(getAuthorizationCache()!=null){
            getAuthorizationCache().clear();
        }
    }

    private void clearAllCachedAuthenticationInfo() {
        if(getAuthenticationCache()!=null){
            getAuthenticationCache().clear();
        }
    }
}